package com.iwhalecloud.bss.kite.cucc.service.shoppingcart.query;

import com.iwhalecloud.bss.kite.client.api.ord.IWithdrawOrderService;
import com.iwhalecloud.bss.kite.client.api.shoppingcart.operate.IOperateShoppingCartItemService;
import com.iwhalecloud.bss.kite.client.api.shoppingcart.operate.IOperateShoppingCartService;
import com.iwhalecloud.bss.kite.client.api.shoppingcart.query.IQueryShoppingCartItemService;
import com.iwhalecloud.bss.kite.client.api.shoppingcart.query.IQueryShoppingCartService;
import com.iwhalecloud.bss.kite.client.dto.DataResult;
import com.iwhalecloud.bss.kite.client.dto.order.ChargeCartItemAndFeeDTO;
import com.iwhalecloud.bss.kite.client.dto.order.RefundOrderDTO;
import com.iwhalecloud.bss.kite.client.dto.shoppingcart.ShoppingCartGroupInstAttrDTO;
import com.iwhalecloud.bss.kite.client.dto.shoppingcart.ShoppingCartGroupInstDTO;
import com.iwhalecloud.bss.kite.client.dto.shoppingcart.ShoppingCartItemDTO;
import com.iwhalecloud.bss.kite.client.dto.shoppingcart.ShoppingCartItemFeeDTO;
import com.iwhalecloud.bss.kite.common.constant.DcPublicConsts;
import com.iwhalecloud.bss.kite.common.constant.ErrorConsts;
import com.iwhalecloud.bss.kite.common.constant.I18nConsts;
import com.iwhalecloud.bss.kite.common.constant.KeyConsts;
import com.iwhalecloud.bss.kite.common.constant.ServiceOfferConsts;
import com.iwhalecloud.bss.kite.common.util.KiteBeanUtils;
import com.iwhalecloud.bss.kite.common.util.KiteListUtils;
import com.iwhalecloud.bss.kite.common.util.KiteObjectUtils;
import com.iwhalecloud.bss.kite.common.util.KiteStringUtils;
import com.iwhalecloud.bss.kite.common.util.SnowflakeUtils;
import com.iwhalecloud.bss.kite.common.util.TransactionUtils;
import com.iwhalecloud.bss.kite.dataservice.cache.DcPublicCache;
import com.iwhalecloud.bss.kite.dataservice.cache.OfferCache;
import com.iwhalecloud.bss.kite.dataservice.cache.ProductCache;
import com.iwhalecloud.bss.kite.dataservice.cache.ServiceOfferCache;
import com.iwhalecloud.bss.kite.dataservice.entity.DcPublic;
import com.iwhalecloud.bss.kite.dataservice.entity.KiteShoppingCartItem;
import com.iwhalecloud.bss.kite.dataservice.entity.OrderItem;
import com.iwhalecloud.bss.kite.dataservice.entity.OrderItemHis;
import com.iwhalecloud.bss.kite.dataservice.entity.Organization;
import com.iwhalecloud.bss.kite.dataservice.entity.ServiceOffer;
import com.iwhalecloud.bss.kite.dataservice.entity.KiteShoppingCartGroupInst;
import com.iwhalecloud.bss.kite.dataservice.entity.KiteShoppingCartGroupInstAttr;
import com.iwhalecloud.bss.kite.dataservice.entity.KiteShoppingCartGroupInstExt;
import com.iwhalecloud.bss.kite.dataservice.entity.fee.PosShoppingCartItemFee;
import com.iwhalecloud.bss.kite.dataservice.entity.fee.KiteShoppingCartItemFee;
import com.iwhalecloud.bss.kite.dataservice.entity.inst.KiteOrderInstRel;
import com.iwhalecloud.bss.kite.dataservice.entity.spec.Offer;
import com.iwhalecloud.bss.kite.dataservice.entity.spec.Product;
import com.iwhalecloud.bss.kite.dataservice.mapper.cashier.CartItemFeeDiscountMapper;
import com.iwhalecloud.bss.kite.dataservice.mapper.fee.ShoppingCartItemFeeMapper;
import com.iwhalecloud.bss.kite.dataservice.mapper.inst.KiteOrderInstRelMapper;
import com.iwhalecloud.bss.kite.dataservice.mapper.order.OrderItemHisMapper;
import com.iwhalecloud.bss.kite.dataservice.mapper.order.OrderItemMapper;
import com.iwhalecloud.bss.kite.dataservice.mapper.other.OrganizationMapper;
import com.iwhalecloud.bss.kite.dataservice.mapper.other.SystemUserMapper;
import com.iwhalecloud.bss.kite.dataservice.mapper.shoppingcart.ShoppingCartGroupInstAttrMapper;
import com.iwhalecloud.bss.kite.dataservice.mapper.shoppingcart.ShoppingCartGroupInstExtMapper;
import com.iwhalecloud.bss.kite.dataservice.mapper.shoppingcart.ShoppingCartGroupInstMapper;
import com.iwhalecloud.bss.kite.dataservice.mapper.shoppingcart.ShoppingCartItemMapper;
import com.iwhalecloud.bss.kite.dataservice.mapper.shoppingcart.ShoppingCartMapper;
import com.iwhalecloud.bss.kite.fee.uitls.FeeCalUtil;
import com.iwhalecloud.bss.kite.manager.api.IQuerySceneInstService;
import com.iwhalecloud.bss.kite.manager.dto.KiteInstRelDTO;
import com.iwhalecloud.bss.kite.manager.dto.KiteSceneInstDTO;
import com.iwhalecloud.bss.kite.manager.enums.InstType;
import com.iwhalecloud.bss.kite.manager.inst.KiteProdInst;
import com.iwhalecloud.bss.kite.manager.inst.KiteProdInstFunc;
import com.iwhalecloud.bss.kite.manager.inst.KiteSceneInst;
import com.iwhalecloud.bss.kite.manager.inst.change.KiteInstChange;
import com.iwhalecloud.bss.kite.manager.inst.change.KiteRelChange;
import com.iwhalecloud.bss.kite.manager.util.ManagerUtils;
import com.iwhalecloud.bss.kite.service.rule.RuleUtil;
import com.iwhalecloud.bss.kite.service.shoppingcart.cache.ShoppingCartGroupCache;
import com.ztesoft.bss.base.staticdata.CoreDataBilling;
import com.ztesoft.bss.base.staticdata.CoreDataInteract;
import com.ztesoft.bss.common.bo.SimpleLoginInfo;
import com.ztesoft.bss.common.exception.BssException;
import com.ztesoft.bss.common.util.ContextUtil;
import com.ztesoft.bss.common.util.I18nUtil;
import com.ztesoft.bss.common.util.SpringUtil;
import com.ztesoft.bss.common.util.StringUtil;
import com.ztesoft.bss.order.base.consts.IKeyValues;
import com.ztesoft.bss.orgauth.entity.SystemPost;
import com.ztesoft.bss.orgauth.entity.SystemUserPost;
import com.ztesoft.bss.orgauth.service.SystemPostService;
import com.ztesoft.bss.orgauth.service.SystemUserPostService;
import com.ztesoft.bss.portal.dto.orderinf.OrderLoginReq;
import com.ztesoft.bss.portal.dto.orderinf.OrderLoginResp;
import com.ztesoft.bss.portal.service.OrderLoginService;
import com.ztesoft.bss.provinces.chongqing.utils.StrTools;
import com.ztesoft.bss.svcability.util.ListUtil;
import com.ztesoft.common.logger.api.ZLogger;
import com.ztesoft.common.logger.factory.ZLoggerFactory;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import tk.mybatis.mapper.entity.Example;
import tk.mybatis.mapper.entity.Example.Criteria;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

@Service("queryShoppingCartService")
public class QueryShoppingCartService implements IQueryShoppingCartService {

    private static final ZLogger LOGGER = ZLoggerFactory.getLogger(QueryShoppingCartService.class, "kite-shoppingCart");

    @Autowired
    IQuerySceneInstService querySceneInstService;

    @Autowired
    IOperateShoppingCartService shoppingCartService;

    @Autowired
    IQueryShoppingCartItemService queryShoppingCartItemService;

    @Autowired
    IOperateShoppingCartItemService operateShoppingCartItemService;

    @Autowired(required=false)
    OrderLoginService orderLoginService;

    @Autowired
    ShoppingCartMapper shoppingCartMapper;

    @Autowired
    ShoppingCartGroupInstMapper shoppingCartGroupInstMapper;

    @Autowired
    ShoppingCartGroupInstAttrMapper shoppingCartGroupInstAttrMapper;

    @Autowired
    ShoppingCartItemMapper shoppingCartItemMapper;

    @Autowired
    ShoppingCartItemFeeMapper shoppingCartItemFeeMapper;

    @Autowired
    ShoppingCartGroupInstExtMapper shoppingCartGroupInstExtMapper;

    @Autowired
    CartItemFeeDiscountMapper cartItemFeeDiscountMapper;

    @Autowired
    OrderItemMapper orderItemMapper;

    @Autowired
    OrderItemHisMapper orderItemHisMapper;

    @Autowired
    SystemUserMapper systemUserMapper;

    @Autowired
    OrganizationMapper organizationMapper;

    @Override
    public Integer getShoppingCartGroupCount(String staffId, String custId) {
        List<String> groupids = new ArrayList<String>();
        List<String> status = new ArrayList<String>();
        status.add(KeyConsts.SHOPPING_CART_GROUP_STATUS_SETTLE);
        status.add(KeyConsts.SHOPPING_CART_GROUP_STATUS_INPUT);
        status.add(KeyConsts.SHOPPING_CART_GROUP_STATUS_CHARGING);
        status.add(KeyConsts.SHOPPING_CART_GROUP_STATUS_CHARGED);
        Example example = new Example(KiteShoppingCartGroupInst.class);
        example.createCriteria().andIn("statusCd", status).andEqualTo("custId", custId);
        List<KiteShoppingCartGroupInst> groupInsts = shoppingCartGroupInstMapper.selectByExample(example);
        if (!KiteListUtils.isEmpty(groupInsts)) {
            for (KiteShoppingCartGroupInst groupInst : groupInsts) {
                groupids.add(groupInst.getGroupId());
            }
        }
        List<ShoppingCartGroupInstDTO> cacheGroups = ShoppingCartGroupCache.getAllGroupInstDtos(staffId, custId);
        if (!KiteListUtils.isEmpty(cacheGroups)) {
            for (ShoppingCartGroupInstDTO groupInst : cacheGroups) {
                if (!Objects.isNull(groupInst) && status.contains(groupInst.getStatusCd()) && !groupids.contains(groupInst.getGroupId())) {
                    groupids.add(groupInst.getGroupId());
                }
            }
        }
        return groupids.size();
    }

    @Override
    public String getCustOrderIdByShoppingCartItems(String sceneInstId, String custId) {
        String custOrderId = "";
        Example itemQryExample = new Example(KiteShoppingCartItem.class);
        itemQryExample.createCriteria().andEqualTo("groupId", sceneInstId).andEqualTo("custId", custId);
        List<KiteShoppingCartItem> groupCartItems = this.shoppingCartItemMapper.selectByExample(itemQryExample);
        if (groupCartItems.size() > 0) {
            custOrderId = groupCartItems.get(0).getCustOrderId();
        }
        return custOrderId;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public List<ShoppingCartGroupInstDTO> createShoppingCartGroups(String staffId, String lanId, String custId) {
        // 获取购物车分组
        return this.listShoppingCartGroups(staffId, lanId, custId);
    }

    @Override
    public List<ShoppingCartGroupInstDTO> querySimpleShoppingCartGroupList(String staffId, String lanId, String custId) {
        List<ShoppingCartGroupInstDTO> groupInstDtos = new ArrayList<ShoppingCartGroupInstDTO>();
        SimpleLoginInfo simpleLoginInfo = this.getSimpleLoginInfo(staffId, lanId);
        groupInstDtos.addAll(this.listAllSimpleShoppingCartGroups(simpleLoginInfo, staffId, custId));
        return groupInstDtos;
    }

    @Override
    public List<ShoppingCartGroupInstDTO> createSimpleShoppingCartGroupList(String staffId, String lanId, String custId) {
        List<ShoppingCartGroupInstDTO> groupInstDtos = new ArrayList<ShoppingCartGroupInstDTO>();
        SimpleLoginInfo simpleLoginInfo = this.getSimpleLoginInfo(staffId, lanId);
        groupInstDtos.addAll(this.listAllSimpleShoppingCartGroupsForRule(simpleLoginInfo, staffId, custId));
        return groupInstDtos;
    }

    @Override
    public List<ShoppingCartGroupInstDTO> listShoppingCartGroupInstAndAmount(String custId, String staffId, List<String> statusCds) {
        // 获取购物车分组
        List<KiteShoppingCartGroupInst> groupInsts = this.shoppingCartGroupInstMapper.listShoppingCartGroupInstAndAmount(custId, staffId, statusCds);
        return KiteBeanUtils.copyPropsForList(groupInsts, ShoppingCartGroupInstDTO.class);
    }

    @Override
    public List<ShoppingCartGroupInstDTO> listShoppingCartGroupInstAndAmount(String custId, String staffId, String statusCd) {
        // 获取购物车分组
        List<KiteShoppingCartGroupInst> groupInsts = this.shoppingCartGroupInstMapper.listShoppingCartGroupInstAndAmount(custId, staffId, java.util.Arrays.asList(statusCd));
        return KiteBeanUtils.copyPropsForList(groupInsts, ShoppingCartGroupInstDTO.class);
    }

    @Override
    public List<ShoppingCartGroupInstDTO> listChargingShoppingCartGoups(String staffId, String lanId, String custId) {
        List<ShoppingCartGroupInstDTO> groupInstDtos = new ArrayList<ShoppingCartGroupInstDTO>();
        // 获取数据库购物车分组
        SimpleLoginInfo simpleLoginInfo = this.getSimpleLoginInfo(staffId, lanId);
        List<KiteShoppingCartGroupInst> groupInsts = this.selectShoppingCartGroupInsts(simpleLoginInfo, staffId, custId);

        if (!KiteListUtils.isEmpty(groupInsts)) {
            groupInsts.forEach((groupInst) -> {
                ShoppingCartGroupInstDTO groupInstDto = packageShoppingCartGroupInstDTO(groupInst, custId, staffId, simpleLoginInfo);
                if (Objects.nonNull(groupInstDto)) {
                    groupInstDtos.add(groupInstDto);
                }
            });
        }
        return groupInstDtos;
    }

    /**
     * 获取录入中和结算中的购物车
     * @param staffId
     * @param custId
     * @return
     */
    private List<ShoppingCartGroupInstDTO> listInputAndSettlementShoppingCartGroups(String staffId, String lanId, String custId) {
        SimpleLoginInfo simpleLoginInfo = this.getSimpleLoginInfo(staffId, lanId);
        List<ShoppingCartGroupInstDTO> groupInstDtos = new ArrayList<ShoppingCartGroupInstDTO>();

        List<String> status = new ArrayList<String>();
        status.add(KeyConsts.SHOPPING_CART_GROUP_STATUS_SETTLE);
        status.add(KeyConsts.SHOPPING_CART_GROUP_STATUS_INPUT);

        Example example = new Example(KiteShoppingCartGroupInst.class);
        example.createCriteria().andIn("statusCd", status).andEqualTo("custId", custId);
        List<KiteShoppingCartGroupInst> groupInsts = shoppingCartGroupInstMapper.selectByExample(example);

        if (!KiteListUtils.isEmpty(groupInsts)) {
            //重新从场景实例里取最新数据组装最新的购物车信息，因为购物车缓存只有进入受理页面和点击保存购物车或去结算按钮时才会保存，进入受理页面后，如果添加了功能产品但是没点保存购物车或去结算按钮，购物车数据不会更新
            for (KiteShoppingCartGroupInst groupInst : groupInsts) {
                ShoppingCartGroupInstDTO groupInstDto = packageShoppingCartGroupInstDTO(groupInst, custId, staffId, simpleLoginInfo);
                if (Objects.nonNull(groupInstDto)) {
                    groupInstDtos.add(groupInstDto);
                }
            }
        }
        return groupInstDtos;
    }

    private ShoppingCartGroupInstDTO packageShoppingCartGroupInstDTO(KiteShoppingCartGroupInst groupInst, String custId, String staffId, SimpleLoginInfo simpleLoginInfo) {
        try {
            KiteSceneInstDTO kiteSceneInstDTO = this.querySceneInstService.getSceneInstDTO(groupInst.getGroupId(), custId);
            if (Objects.nonNull(kiteSceneInstDTO)) {
                ShoppingCartGroupInstDTO groupInstDto = this.shoppingCartService.createShoppingCartGroupInstInfo(simpleLoginInfo, kiteSceneInstDTO, groupInst.getStatusCd(), staffId, custId).getResultObject();
                KiteBeanUtils.copyProperties(groupInst, groupInstDto);
                return groupInstDto;
            }
            else {
                //数据库没有购物车数据，没有场景实例，删除购物车缓存
                ShoppingCartGroupCache.removeGroupInstDto(staffId, custId, groupInst.getGroupId());
            }
        }
        catch (BssException e) {
            String failCode = e.getFailCode();
            // 场景实例不存在的异常不往外抛，直接返回null
            if (!ErrorConsts.SCENE_INST_NOT_EXISTS.getCode().equals(failCode) && !ErrorConsts.PROD_INST_NOT_EXIST.getCode().equals(failCode) && !ErrorConsts.INST_NOT_EXIST.getCode().equals(failCode)) {
                throw e;
            }
            List<String> groupIds = new ArrayList<>();
            groupIds.add(groupInst.getGroupId());
            TransactionUtils.executeNew(() -> this.shoppingCartService.deleteShoppingCartGroups(staffId,
                simpleLoginInfo.getOrgId().toString(), simpleLoginInfo.getLanId(), custId, groupIds,
                I18nConsts.BSS_KITE_SHOPPING_CART_90005.getMessage(), false));
        }
        return null;
    }

    /**
     * 获取工号班组长岗位的受理组织
     * @return
     */
    private List<String> selectTeamers(String sysUserId, String orgId) {
        DcPublic dcPublic = DcPublicCache.get("20190901002", "TeamLeaderPostCode");
        if (Objects.isNull(dcPublic) || KiteStringUtils.isEmpty(dcPublic.getCodea())) {
            return new ArrayList<>();
        }
        String teamLeaderPostCode = dcPublic.getCodea();
        //查询当前工号，班组长岗位所在的受理组织
        SystemPostService systemPostService = SpringUtil.getBean(SystemPostService.class);
        SystemUserPostService systemUserPostService = SpringUtil.getBean(SystemUserPostService.class);
        //查当前工号，在当前组织的任职岗位
        Long sysUserIdd = Long.valueOf(sysUserId);
        Long orgIdd = Long.valueOf(orgId);
        List<SystemUserPost> sysUserPosts = null;
        try {
            sysUserPosts = systemUserPostService.selectByUserIdAndOrgId(sysUserIdd, orgIdd);
        }
        catch (Exception e) {
            LOGGER.error(null, e.getMessage());
        }
        if (KiteListUtils.isEmpty(sysUserPosts)) {
            return new ArrayList<>();
        }
        List<String> orgIds = new ArrayList<>();
        for (SystemUserPost userPost : sysUserPosts) {
            SystemPost post = systemPostService.selectByPrimaryKey(userPost.getSysPostId());
            if (Objects.nonNull(post) && KiteStringUtils.equals(teamLeaderPostCode, post.getSysPostCode())) {
                orgIds.add(String.valueOf(userPost.getOrgId()));
            }
        }
        if (KiteListUtils.isEmpty(orgIds)) {
            return new ArrayList<>();
        }
        Example example = new Example(Organization.class);
        example.createCriteria().andIn("orgId", orgIds).andEqualTo("statusCd", KeyConsts.COMMON_STATUS_VALIDATE);
        List<Organization> orgs = this.organizationMapper.selectByExample(example);
        if (KiteListUtils.isEmpty(orgs)) {
            return new ArrayList<>();
        }
        List<String> orgPathCodes = new ArrayList<>();
        orgs.forEach((organization) -> {
            orgPathCodes.add(organization.getPathCode());
        });
        return this.systemUserMapper.selectTeamers(orgPathCodes);
    }

    public List<KiteShoppingCartGroupInst> selectShoppingCartGroupInsts(SimpleLoginInfo simpleLoginInfo, String sysUserId, String custId) {
        List<String> teamerIds = new ArrayList<>();
        String filterFlag = DcPublicCache.getCodea(DcPublicConsts.DC_SHPCART_FILTER_BY_STAFF_STYPE, DcPublicConsts.DC_SHPCART_FILTER_BY_STAFF_PKEY);
        if (!KiteStringUtils.isEmpty(sysUserId) && KeyConsts.IFTRUE_Y.equals(filterFlag)) {
            //没有受理组织时（外系统调dubbo服务）
            if (Objects.nonNull(simpleLoginInfo)) {
                //获取班组营业员
                teamerIds = this.selectTeamers(sysUserId, simpleLoginInfo.getOrgId().toString());
            }
            //加自己
            teamerIds.add(sysUserId);
        }

        List<String> status = new ArrayList<String>();
        status.add(KeyConsts.SHOPPING_CART_GROUP_STATUS_INPUT);
        status.add(KeyConsts.SHOPPING_CART_GROUP_STATUS_SETTLE);
        status.add(KeyConsts.SHOPPING_CART_GROUP_STATUS_CHARGING);
        status.add(KeyConsts.SHOPPING_CART_GROUP_STATUS_CHARGED);
        //status.add(KeyConsts.SHOPPING_CART_GROUP_STATUS_REFUND);

        Example example = new Example(KiteShoppingCartGroupInst.class);
        example.createCriteria().andIn("statusCd", status).andEqualTo("custId", custId);
        if (!KiteListUtils.isEmpty(teamerIds)) {
            example.createCriteria().andIn("statusCd", status).andEqualTo("custId", custId);
        }
        else {
            example.createCriteria().andIn("statusCd", status).andEqualTo("custId", custId).andIn("createStaff", teamerIds);
        }
        return this.shoppingCartGroupInstMapper.selectShoppingCartGroupInsts(teamerIds, custId, status);
    }


    /**
     * 获取收费中的简单购物车列表
     * @param sysUserId
     * @param custId
     * @return
     */
    private List<ShoppingCartGroupInstDTO> listAllSimpleShoppingCartGroups(SimpleLoginInfo simpleLoginInfo, String sysUserId, String custId) {
        //获取数据库购物车分组
        List<ShoppingCartGroupInstDTO> groupInstDtos = new ArrayList<ShoppingCartGroupInstDTO>();
        List<KiteShoppingCartGroupInst> groupInsts = this.selectShoppingCartGroupInsts(simpleLoginInfo, sysUserId, custId);
        for (KiteShoppingCartGroupInst groupInst : groupInsts) {
            //如果是待录入，缓存数据不存在（超过有效时间）则删除表中的数据，不返回前端展示
            if (KeyConsts.SHOPPING_CART_GROUP_STATUS_INPUT.equals(groupInst.getStatusCd())) {
                ShoppingCartGroupInstDTO cacheGroupInstDto = ShoppingCartGroupCache.getGroupInstDto(sysUserId, custId, groupInst.getGroupId());
                if (KiteObjectUtils.isEmpty(cacheGroupInstDto)) {
                    TransactionUtils.executeNew(() -> this.shoppingCartService.deleteShoppingCartGroupInfo(groupInst.getGroupId(), custId, sysUserId, Boolean.TRUE));
                    continue;
                }
            }
            ShoppingCartGroupInstDTO groupInstDto = this.shoppingCartService.createSimpleShoppingCartGroupInstInfo(simpleLoginInfo, groupInst.getGroupId(), groupInst.getStatusCd(), groupInst.getCreateStaff(), custId).getResultObject();
            if (Objects.nonNull(groupInstDto)) {
              //查产品实例变动和关系变动，没有变动的产品不展示
                List<KiteInstChange> instChanges = querySceneInstService.listInstChanges(groupInstDto.getGroupId());
                List<KiteRelChange> relChanges = querySceneInstService.listRelChanges(groupInstDto.getGroupId());

                List<String> prodInstIds = instChanges.stream()
                    .filter(kiteInstChange -> InstType.PROD_INST == kiteInstChange.getSubInstType())
                    .map(KiteInstChange::getSubInstId).collect(Collectors.toList());

                List<ShoppingCartItemDTO> showCartItems = new ArrayList<>();
                List<ShoppingCartItemDTO> cartItems = groupInstDto.getShoppingCartItems();
                for (ShoppingCartItemDTO cartItem : cartItems) {
                    //如果是k，判断有没有变动，有变动则展示
                    if (KiteStringUtils.equals(CoreDataInteract.EVT_C_0002_1300, cartItem.getOperType())) {
                        String instId = cartItem.getObjId();
                        if (KeyConsts.SHOPPING_CART_ITEM_CD_CP.equals(cartItem.getCartItemCd())) {
                            boolean isFound = false;
                            for (KiteInstChange change : instChanges) {
                                //如果修改的是可选包属性，找可选包的接入产品进行判断
                                if (Objects.equals(InstType.ADDITIONAL_OFFER_INST, change.getInstType())) {
                                    List<KiteInstRelDTO> instRels = querySceneInstService.listInstRelsByAInst(cartItem.getCustId(), InstType.ADDITIONAL_OFFER_INST, change.getInstId(), InstType.PROD_INST);
                                    String zInstId = KiteListUtils.isEmpty(instRels) ? null : instRels.get(0).getzInstId();
                                    if (KiteStringUtils.equals(zInstId, instId)) {
                                        showCartItems.add(cartItem);
                                        isFound = true;
                                        break;
                                    }
                                }
                                else if (Objects.equals(InstType.PROD_INST_FUNC, change.getInstType())) {
                                    List<KiteInstRelDTO> instRels = querySceneInstService.listInstRelsByZInst(cartItem.getCustId(), InstType.PROD_INST_FUNC, change.getInstId(), InstType.PROD_INST);
                                    String zInstId = KiteListUtils.isEmpty(instRels) ? null : instRels.get(0).getaInstId();
                                    if (KiteStringUtils.equals(zInstId, instId)) {
                                        showCartItems.add(cartItem);
                                        isFound = true;
                                        break;
                                    }
                                }
                            }
                            //如果通过可选包变动已经找到，则不需要继续找变动进行判断
                            if (isFound) {
                                continue;
                            }
                            boolean flag = instChanges.stream().anyMatch(t -> Objects.equals(t.getInstType(), InstType.PROD_INST) && KiteStringUtils.equals(t.getInstId(), instId));
                            if (!flag) {
                                flag =  relChanges.stream().anyMatch(t -> (Objects.equals(t.getSourceInstType(), InstType.PROD_INST) && KiteStringUtils.equals(t.getSourceInstId(), instId)) || (Objects.equals(t.getTargetInstType(), InstType.PROD_INST) && KiteStringUtils.equals(t.getTargetInstId(), instId)));
                            }
                            if (flag) {
                                showCartItems.add(cartItem);
                            }
                        }
                    }
                    else {
                        //如果不是k直接添加到result，在收费页面展示
                        if (prodInstIds.contains(cartItem.getProdInstId())) {
                            //过滤关联产品号码
                            showCartItems.add(cartItem);
                        }
                    }
                }
                groupInstDto.setShoppingCartItems(showCartItems);
                KiteBeanUtils.copyProperties(groupInst, groupInstDto);
                groupInstDtos.add(groupInstDto);
            }
        }
        return groupInstDtos;
    }

    private List<ShoppingCartGroupInstDTO> listAllSimpleShoppingCartGroupsForRule(SimpleLoginInfo simpleLoginInfo, String sysUserId, String custId) {
        //获取数据库购物车分组
        List<ShoppingCartGroupInstDTO> groupInstDtos = new ArrayList<ShoppingCartGroupInstDTO>();
        List<KiteShoppingCartGroupInst> groupInsts = this.selectShoppingCartGroupInsts(simpleLoginInfo, sysUserId, custId);
        for (KiteShoppingCartGroupInst groupInst : groupInsts) {
            //如果是待录入，缓存数据不存在（超过有效时间）则删除表中的数据，不返回前端展示
            if (KeyConsts.SHOPPING_CART_GROUP_STATUS_INPUT.equals(groupInst.getStatusCd())) {
                ShoppingCartGroupInstDTO cacheGroupInstDto = ShoppingCartGroupCache.getGroupInstDto(sysUserId, custId, groupInst.getGroupId());
                if (KiteObjectUtils.isEmpty(cacheGroupInstDto)) {
                    TransactionUtils.executeNew(() -> this.shoppingCartService.deleteShoppingCartGroupInfo(groupInst.getGroupId(), custId, sysUserId, Boolean.TRUE));
                    continue;
                }
            }
            ShoppingCartGroupInstDTO groupInstDto = this.shoppingCartService.createSimpleShoppingCartGroupInstInfoForRule(simpleLoginInfo, groupInst.getGroupId(), groupInst.getStatusCd(), groupInst.getCreateStaff(), custId).getResultObject();
            if (Objects.nonNull(groupInstDto)) {
                KiteBeanUtils.copyProperties(groupInst, groupInstDto);
                groupInstDtos.add(groupInstDto);
            }
        }
        return groupInstDtos;
    }

    private List<ShoppingCartGroupInstDTO> listShoppingCartGroups(String staffId, String lanId, String custId) {
        List<ShoppingCartGroupInstDTO> groups = new ArrayList<ShoppingCartGroupInstDTO>();
        // 待收费的直接查数据库，购物车入库后不能修改，不需要重新从场景对象组装
        groups.addAll(this.listChargingShoppingCartGoups(staffId, lanId, custId));
        // 获取待录入和待结算购物车
        groups.addAll(this.listInputAndSettlementShoppingCartGroups(staffId, lanId, custId));
        return groups;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public String getShoppingCartGroupTotalFee(String sceneInstId, String custId, String userId, String lanId) {
        Assert.hasText(sceneInstId, "sceneInstId must not be empty");
        ShoppingCartGroupInstDTO groupInstDto = ShoppingCartGroupCache.getGroupInstDto(userId, custId, sceneInstId);
        if (Objects.isNull(groupInstDto)) {
            return "0";
        }
        return operateShoppingCartItemService.sumTotalAmount(sceneInstId, custId);
    }

    @Override
    public String parseToKiteSceneInst(String sceneInstId, String custId) {
        Example example = new Example(KiteShoppingCartGroupInstExt.class);
        example.createCriteria().andEqualTo("statusCd", KeyConsts.SHOPPING_CART_STATUS_VALIDATE)
        .andEqualTo("groupInstExtId", sceneInstId).andEqualTo("custId", custId);
        List<KiteShoppingCartGroupInstExt> instExts = shoppingCartGroupInstExtMapper.selectByExample(example);
        if (KiteListUtils.isEmpty(instExts)) {
            ErrorConsts.SHOPPING_CART_GROUP_INST_EXT_NULL_ERROR.throwOut(sceneInstId);
        }
        KiteShoppingCartGroupInstExt instExt = instExts.get(0);
        String json = instExt.getAttrJson();
        return json;
    }

    @Override
    public DataResult<List<ShoppingCartItemDTO>> listShoppingCartItems(String custOrderId, String custId) {
        Example example = new Example(KiteShoppingCartItem.class);
        example.createCriteria().andEqualTo("custOrderId", custOrderId).andEqualTo("custId", custId);
        List<KiteShoppingCartItem> ShoppingCartItems = shoppingCartItemMapper.listChargeShoppingCartItems(custOrderId, custId);
        //List<ShoppingCartItem> ShoppingCartItems = shoppingCartItemMapper.selectByExample(example);
        if (KiteListUtils.isEmpty(ShoppingCartItems)) {
            return new DataResult<List<ShoppingCartItemDTO>>();
        }
        return ErrorConsts.SUCCESS
            .getResult(KiteBeanUtils.copyPropsForList(ShoppingCartItems, ShoppingCartItemDTO.class));
    }

    @Override
    public DataResult<List<ChargeCartItemAndFeeDTO>> listShoppingCartItemsAndFees(String custOrderId, String custId) {
        return listShoppingCartItemsAndFees(custOrderId, custId, "");
    }

    @Override
    public DataResult<List<ChargeCartItemAndFeeDTO>> listShoppingCartItemsAndFees(String custOrderId, String custId, String groupId) {
        Example example = new Example(KiteShoppingCartItem.class);
        example.createCriteria().andEqualTo("custOrderId", custOrderId).andEqualTo("custId", custId);

        List<ShoppingCartGroupInstDTO> groupInstDtos = this.getGroupInstDTOByCustOrderId(custOrderId, custId).getResultObject();
        ShoppingCartGroupInstDTO groupInstDto = groupInstDtos.get(0);
        // 查出所有产品的，费用不为0 的订单项和费用项
        List<ChargeCartItemAndFeeDTO> shoppingCartItemsAndFees = new ArrayList<>();
        shoppingCartItemsAndFees.addAll(shoppingCartItemMapper.listChargeShoppingCartItemsAndFees(custOrderId, custId));
        shoppingCartItemsAndFees.addAll(shoppingCartItemMapper.listChargeShoppingCartItemsAndFeesFromHis(custOrderId, custId));
        //如果没生成费用，如宽带和ITV停机，先不关联费用查询，生成一个默认的0的费用返回 -- 临时处理办法额
        if (KiteListUtils.isEmpty(shoppingCartItemsAndFees)) {
            shoppingCartItemsAndFees.addAll(shoppingCartItemMapper.listChargeShoppingCartItemsWithoutFee(custOrderId, custId));
        }
        //撤单过滤已经竣工的订单项
        if (KeyConsts.SERVICE_WITHDRAW.equals(groupInstDto.getServiceOfferId())) {
            String oldGroupId = groupInstDto.getOldGroupId();
            ShoppingCartGroupInstDTO oldGroupInstDto = this.getGroupInstDTOByGroupId(oldGroupId, custId).getResultObject();
            if (Objects.isNull(oldGroupInstDto)) {
                oldGroupInstDto = this.getShoppingGroupInstHis(oldGroupId, custId).getResultObject();
            }
            //不展示已竣工的，临时方法，待manager提供remove实例api后改为初始化撤单场景时remove不撤的实例
            Example qryHisExample = new Example(OrderItemHis.class);
            qryHisExample.createCriteria().andEqualTo("custOrderId", oldGroupInstDto.getCustOrderId()).andEqualTo("belongCustId", custId);
            List<OrderItemHis> finishedOrderItems = this.orderItemHisMapper.selectByExample(qryHisExample);
            if (!KiteListUtils.isEmpty(finishedOrderItems)) {
                List<String> objIds = new ArrayList<>();
                finishedOrderItems.forEach((item) -> {
                    IWithdrawOrderService marketOrderService = SpringUtil.getBean(IWithdrawOrderService.class);
                    String objId = marketOrderService.getInstIdByCompInstId(item.getOfferKind(), item.getObjId(), custId);
                    if (!KiteStringUtils.isEmpty(objId)) {
                        objIds.add(objId);
                    }
                });

                shoppingCartItemsAndFees = shoppingCartItemsAndFees.stream()
                        .filter(item -> !objIds.contains(item.getObjId())).collect(Collectors.toList());
            }
            //不展示不一起撤单的，临时方法，待manager提供remove实例api后改为初始化撤单场景时remove不撤的实例
            Example qryExample = new Example(OrderItem.class);
            qryExample.createCriteria().andEqualTo("custOrderId", oldGroupInstDto.getCustOrderId()).andEqualTo("belongCustId", custId);
            List<OrderItem> orderItems = this.orderItemMapper.selectByExample(qryExample);
            String revokeOrderItemId = this.querySceneInstService.getExtParameterValue(groupInstDto.getGroupId(), "revokeOrderItemId");
            if (!KiteStringUtils.isEmpty(revokeOrderItemId) && !KiteListUtils.isEmpty(orderItems)) {
                List<String> revokeOrderItemIds = Arrays.asList(revokeOrderItemId.split(","));
                List<OrderItem> notShowOrderItems = orderItems.stream().filter(item -> !revokeOrderItemIds.contains(item.getOrderItemId())).collect(Collectors.toList());

                List<String> objIds = new ArrayList<>();
                notShowOrderItems.forEach((item) -> {
                    IWithdrawOrderService marketOrderService = SpringUtil.getBean(IWithdrawOrderService.class);
                    String objId = marketOrderService.getInstIdByCompInstId(item.getOfferKind(), item.getObjId(), custId);
                    if (!KiteStringUtils.isEmpty(objId)) {
                        objIds.add(objId);
                    }

                });
                shoppingCartItemsAndFees = shoppingCartItemsAndFees.stream()
                        .filter(item -> !objIds.contains(item.getObjId())).collect(Collectors.toList());
                //TODO 宽带订单项撤单时，需要把固话可选包排除
            }
        }

        List<ChargeCartItemAndFeeDTO> showItemFees = new ArrayList<>();
        // 产品可能有0-n条费用,若有不为0的,筛选掉为0的费用;若没有不为0的,筛选剩一条为0的费用
        List<ChargeCartItemAndFeeDTO> showOfferItemFees = shoppingCartItemsAndFees.stream()
            .filter(item -> !Objects.equals(item.getCartItemCd(), KeyConsts.SHOPPING_CART_ITEM_CD_CP)).collect(Collectors.toList());
        showItemFees.addAll(showOfferItemFees);

        List<ChargeCartItemAndFeeDTO> showProdItemFees = shoppingCartItemsAndFees.stream()
                .filter(item -> Objects.equals(item.getCartItemCd(), KeyConsts.SHOPPING_CART_ITEM_CD_CP)).collect(Collectors.toList());
        //筛选没有实例变动的产品项，迁转不筛选
        if (!ServiceOfferConsts.SERVICE_OFFER_FUSION_TRANSFER.equals(groupInstDto.getServiceOfferId())) {
            List<ChargeCartItemAndFeeDTO> restshowProdItemFees = filterShowChargeCartItems(showProdItemFees, groupId);
            showItemFees.addAll(restshowProdItemFees);
        }
        else {
            showItemFees.addAll(showProdItemFees);
        }
        if (!ServiceOfferConsts.SERVICE_OFFER_REVOKE.equals(groupInstDto.getServiceOfferId())) {
            showItemFees = removeRepeatItemFees(showItemFees);
        }
        showItemFees = selectSpecName(showItemFees, custId);
        showItemFees = sortItemFees(showItemFees);
        return ErrorConsts.SUCCESS.getResult(showItemFees);
    }

    /**
     * 排序-金额大于0的排前
     * @param itemFees
     * @return
     */
    private List<ChargeCartItemAndFeeDTO> sortItemFees(List<ChargeCartItemAndFeeDTO> itemFees) {
        if (KiteListUtils.isEmpty(itemFees)) {
            return Collections.emptyList();
        }
        itemFees = itemFees.stream()
                .sorted(Comparator.comparing(ChargeCartItemAndFeeDTO::getApplyObjSpec).thenComparing(ChargeCartItemAndFeeDTO::getAmount).reversed())
                .collect(Collectors.toList());
        List<ChargeCartItemAndFeeDTO> hasFeeAmountList = new ArrayList<>();
        List<ChargeCartItemAndFeeDTO> noFeeAmountList = new ArrayList<>();
        for (ChargeCartItemAndFeeDTO itemFee : itemFees) {
            if (!"0.00".equals(itemFee.getAmount()) || !"0.00".equals(itemFee.getPerferAmount())) {
                hasFeeAmountList.add(itemFee);
            }
            else {
                noFeeAmountList.add(itemFee);
            }
        }
        hasFeeAmountList.addAll(noFeeAmountList);
        return hasFeeAmountList;
    }

    /**
     * 金额为0的购物项费用去重
     * @param itemFees
     */
    private List<ChargeCartItemAndFeeDTO> removeRepeatItemFees(List<ChargeCartItemAndFeeDTO> itemFees) {
        Map<String, String> keyMap = new HashMap<>();
        List<ChargeCartItemAndFeeDTO> showItemFees = new ArrayList<ChargeCartItemAndFeeDTO>();
        for (ChargeCartItemAndFeeDTO itemFee : itemFees) {
            if ("0.00".equals(itemFee.getAmount()) && "0.00".equals(itemFee.getPerferAmount())) {
                //不展示费用为0的可选包
                if (KeyConsts.SHOPPING_CART_ITEM_CD_XSP.equals(itemFee.getCartItemCd())) {
                    String offerId = itemFee.getApplyObjSpec();
                    Offer offer = OfferCache.get(offerId);
                    if (KiteObjectUtils.isEmpty(offer)) {
                        ErrorConsts.OFFER_NOT_FOUND.throwOut(offerId);
                    }
                    if (KeyConsts.OFFER_TYPE_12.equals(offer.getOfferType())) {
                        continue;
                    }
                }
                //删除费用为0的重复费用项
                StringBuilder key = new StringBuilder();
                key.append(itemFee.getObjId()).append(itemFee.getAcctItemTypeId()).append(itemFee.getAmount());
                if (!keyMap.containsKey(key.toString())) {
                    keyMap.put(key.toString(), "1");
                    showItemFees.add(itemFee);
                }
            }
            else {
                showItemFees.add(itemFee);
            }
        }
        return showItemFees;
    }

    /**
     * 对销售品进行一个简单的过滤（销售品解体成员不拆机，在收费页面展示退订套餐，否则没订单展示）
     * @param listChargeCartItemAndFee
     * @return
     */
    /*private List<ChargeCartItemAndFeeDTO> filterShowChargeOfferItems(List<ChargeCartItemAndFeeDTO> listChargeCartItemAndFee, String groupId) {
        List<ChargeCartItemAndFeeDTO> showItemFees = new ArrayList<>();

        for (ChargeCartItemAndFeeDTO chargeCartItemAndFee: listChargeCartItemAndFee) {
            if (!"0.00".equals(chargeCartItemAndFee.getAmount()) || (!CoreDataInteract.EVT_C_0002_1300.equals(chargeCartItemAndFee.getOperType())
                    && !CoreDataInteract.EVT_C_0002_1000.equals(chargeCartItemAndFee.getOperType()))) {
                showItemFees.add(chargeCartItemAndFee);
            }
        }
        return showItemFees;
    }*/

    private List<ChargeCartItemAndFeeDTO> filterShowChargeCartItems(List<ChargeCartItemAndFeeDTO> listChargeCartItemAndFee, String groupId) {
        List<ChargeCartItemAndFeeDTO> showItemFees = new ArrayList<>();
        //查产品实例变动和关系变动，没有变动的产品不展示
        List<KiteInstChange> instChanges = querySceneInstService.listInstChanges(groupId);
        List<KiteRelChange> relChanges = querySceneInstService.listRelChanges(groupId);
        for (ChargeCartItemAndFeeDTO chargeCartItemAndFee: listChargeCartItemAndFee) {
            //撤单直接返回
            if (KeyConsts.SERVICE_WITHDRAW.equals(chargeCartItemAndFee.getServiceOfferId())) {
                showItemFees.add(chargeCartItemAndFee);
                continue;
            }
            //如果是k，判断有没有变动，有变动则展示
            //增加D的过滤，前一个场景做拆机（包含固话），后一个场景做号码的停机，后一个场景的固话是没有变动的，不需要展示
            if (KiteStringUtils.equals(CoreDataInteract.EVT_C_0002_1300, chargeCartItemAndFee.getOperType())
                    || KiteStringUtils.equals(CoreDataInteract.EVT_C_0002_1100, chargeCartItemAndFee.getOperType())) {
                String instId = chargeCartItemAndFee.getObjId();
                if (KeyConsts.SHOPPING_CART_ITEM_CD_CP.equals(chargeCartItemAndFee.getCartItemCd())) {
                    boolean isFound = false;
                    for (KiteInstChange change : instChanges) {
                        //如果修改的是可选包属性，找可选包的接入产品进行判断
                        if (Objects.equals(InstType.ADDITIONAL_OFFER_INST, change.getInstType())) {
                            List<KiteInstRelDTO> instRels = querySceneInstService.listInstRelsByAInst(chargeCartItemAndFee.getCustId(), InstType.ADDITIONAL_OFFER_INST, change.getInstId(), InstType.PROD_INST);
                            String zInstId = KiteListUtils.isEmpty(instRels) ? null : instRels.get(0).getzInstId();
                            if (KiteStringUtils.equals(zInstId, instId)) {
                                showItemFees.add(chargeCartItemAndFee);
                                isFound = true;
                                break;
                            }
                        }
                        else if (Objects.equals(InstType.PROD_INST_FUNC, change.getInstType())) {
                            List<KiteInstRelDTO> instRels = querySceneInstService.listInstRelsByZInst(chargeCartItemAndFee.getCustId(), InstType.PROD_INST_FUNC, change.getInstId(), InstType.PROD_INST);
                            String zInstId = KiteListUtils.isEmpty(instRels) ? null : instRels.get(0).getaInstId();
                            if (KiteStringUtils.equals(zInstId, instId)) {
                                showItemFees.add(chargeCartItemAndFee);
                                isFound = true;
                                break;
                            }
                        }
                        else if (Objects.equals(InstType.MKT_RES_INST, change.getInstType())) {
                            List<KiteInstRelDTO> instRels = querySceneInstService.listInstRelsByZInst(chargeCartItemAndFee.getCustId(), InstType.MKT_RES_INST, change.getInstId(), InstType.PROD_INST);
                            String zInstId = KiteListUtils.isEmpty(instRels) ? null : instRels.get(0).getaInstId();
                            if (KiteStringUtils.equals(zInstId, instId)) {
                                showItemFees.add(chargeCartItemAndFee);
                                isFound = true;
                                break;
                            }
                        }
                    }
                    //如果通过可选包变动已经找到，则不需要继续找变动进行判断
                    if (isFound) {
                        continue;
                    }
                    boolean flag = instChanges.stream().anyMatch(t -> Objects.equals(t.getInstType(), InstType.PROD_INST) && KiteStringUtils.equals(t.getInstId(), instId));
                    if (!flag) {
                        flag =  relChanges.stream().anyMatch(t -> (Objects.equals(t.getSourceInstType(), InstType.PROD_INST) && KiteStringUtils.equals(t.getSourceInstId(), instId)) || (Objects.equals(t.getTargetInstType(), InstType.PROD_INST) && KiteStringUtils.equals(t.getTargetInstId(), instId)));
                    }
                    if (flag) {
                        showItemFees.add(chargeCartItemAndFee);
                    }
                }
            }
            else {
                //如果不是k直接添加到result，在收费页面展示
                showItemFees.add(chargeCartItemAndFee);
            }
        }
        return showItemFees;
    }

    @Override
    public DataResult<List<ShoppingCartItemFeeDTO>> listShoppingCartItemFees(String custOrderId, String custId) {
        List<KiteShoppingCartItemFee> shoppingCartItemFees = shoppingCartItemFeeMapper
            .listShoppingCartItemFeesByCustOrderId(custOrderId, custId);
        return ErrorConsts.SUCCESS
            .getResult(KiteBeanUtils.copyPropsForList(shoppingCartItemFees, ShoppingCartItemFeeDTO.class));
    }

    @Override
    public List<ShoppingCartItemFeeDTO> listShoppingCartItemFeesByGroupId(String groupId, String custId) {
        List<KiteShoppingCartItemFee> shoppingCartItemFees = shoppingCartItemFeeMapper.listShoppingCartItemFeesByGroupId(groupId, custId);
        if (CollectionUtils.isEmpty(shoppingCartItemFees)) {
            return Collections.emptyList();
        }
        return KiteBeanUtils.copyPropsForList(shoppingCartItemFees, ShoppingCartItemFeeDTO.class);
    }

    @Override
    public boolean isShoppingCartFeeDiscounted(String shoppingCartItemFeeId, String custId) {
        String flag = cartItemFeeDiscountMapper.qryCartItemFeeDiscount(shoppingCartItemFeeId, custId);
        return "1".equals(flag);
    }

    @Override
    public boolean isShoppingCartFeesDiscounted(List<String> shoppingCartItemFeeIds, String custId) {
        if (CollectionUtils.isEmpty(shoppingCartItemFeeIds)) {
            return false;
        }
        List<String> flags = cartItemFeeDiscountMapper.qryCartItemFeesDiscount(shoppingCartItemFeeIds, custId);
        return CollectionUtils.isNotEmpty(flags);
    }

    private List<ChargeCartItemAndFeeDTO> selectSpecName(List<ChargeCartItemAndFeeDTO> itemFeeList, String custId) {
        if (KiteListUtils.isEmpty(itemFeeList)) {
            return null;
        }
        String paymentMethod = CoreDataBilling.OTC_0001_100000; //没有费用的默认支付方式
        List<String> instIds = new ArrayList<String>();
        for (ChargeCartItemAndFeeDTO shoppingCartItem : itemFeeList) {
            instIds.add(shoppingCartItem.getObjId());
            if (!KiteStringUtils.isEmpty(shoppingCartItem.getPaymentMethod())) {
                paymentMethod = shoppingCartItem.getPaymentMethod();
            }
        }
        String defaultPaymentMethod = paymentMethod;
        Map<String, OrderItem> procInstMap = this.getSpecNameByProductInst(instIds, custId);
        Map<String, OrderItem> useInstMap = this.getSpecNameByProdInst(instIds, custId);
        itemFeeList.forEach((shoppingCartItem) -> {
            shoppingCartItem = selectOneName(shoppingCartItem, procInstMap, useInstMap);
            // 订单项无对应费用项，添加默认展示的
            if (KiteStringUtils.isEmpty(shoppingCartItem.getShoppingCartItemFeeId())) {
                shoppingCartItem.setShoppingCartItemFeeId(SnowflakeUtils.generateId().toString());
                shoppingCartItem.setAmount("0.00");
                shoppingCartItem.setPerferAmount("0.00");
                shoppingCartItem.setAdjustAmount("0.00");
                shoppingCartItem.setNeedAmount("0.00");
                shoppingCartItem.setPayAmount("0.00");
                shoppingCartItem.setAcctItemTypeId("-1");
                shoppingCartItem.setPaymentMethod(defaultPaymentMethod);
                shoppingCartItem.setPayTacheType("0");
            }
        });

        List<ChargeCartItemAndFeeDTO> processList = itemFeeList.stream()
            .filter(l -> KiteStringUtils.equals(l.getApplyObjSpec(), "2020966")).collect(Collectors.toList());

        //手机主副卡排序
        if (KiteListUtils.isNotEmpty(processList)) {
            List<ChargeCartItemAndFeeDTO> sortedList = processList.stream()
                .sorted(Comparator.comparing(ChargeCartItemAndFeeDTO::getRoleId)).collect(Collectors.toList());
            itemFeeList.removeAll(processList);
            sortedList.addAll(itemFeeList);
            return sortedList;
        }

        return itemFeeList;
    }

    private Map<String, OrderItem> getSpecNameByProductInst(List<String> instIds, String custId) {
        Map<String, OrderItem> map = new HashMap<String, OrderItem>();
        List<OrderItem> items = orderItemMapper.listSpecNameByProductInsts(instIds, custId);
        if (!KiteListUtils.isEmpty(items)) {
            items.forEach((item) -> {
                map.put(item.getObjId(), item);
            });
        }
        return map;
    }

    private Map<String, OrderItem> getSpecNameByProdInst(List<String> instIds, String custId) {
        Map<String, OrderItem> map = new HashMap<String, OrderItem>();
        List<OrderItem> items = orderItemMapper.listSpecNameByProdInsts(instIds, custId);
        if (!KiteListUtils.isEmpty(items)) {
            items.forEach((item) -> {
                map.put(item.getObjId(), item);
            });
        }
        return map;
    }

    private ChargeCartItemAndFeeDTO selectOneName(ChargeCartItemAndFeeDTO chargeOrderItemAndFeeDTO, Map<String, OrderItem> procInstMap, Map<String, OrderItem> useInstMap) {
        //TOTO 耗时高待优化
        // 销售品
        if (Objects.equals(CoreDataInteract.EVT_0003_1200, chargeOrderItemAndFeeDTO.getCartItemCd())) {
            long time1 = System.currentTimeMillis();
            Offer offer = OfferCache.get(chargeOrderItemAndFeeDTO.getApplyObjSpec());
            chargeOrderItemAndFeeDTO.setOfferName(offer.getOfferName());
            long time2 = System.currentTimeMillis();
            LOGGER.debug("取销售品规格==============" + (time2 - time1));
        }
        // 接入产品
        else if (Objects.equals(CoreDataInteract.EVT_0003_1300, chargeOrderItemAndFeeDTO.getCartItemCd())
                || Objects.equals(KeyConsts.SHOPPING_CART_ITEM_CD_YXZY, chargeOrderItemAndFeeDTO.getCartItemCd())) {
            long time1 = System.currentTimeMillis();
            Product product = ProductCache.get(chargeOrderItemAndFeeDTO.getApplyObjSpec());
            chargeOrderItemAndFeeDTO.setSpecName(product.getProdName());
            KiteProdInst prodInst = querySceneInstService.getProdInst(chargeOrderItemAndFeeDTO.getCustId(),
                chargeOrderItemAndFeeDTO.getObjId());
            if (!Objects.isNull(prodInst)) {
                chargeOrderItemAndFeeDTO.setAccNum(prodInst.getAccNum());
                chargeOrderItemAndFeeDTO.setRoleId(prodInst.getRoleId());
                if (KiteStringUtils.isEmpty(prodInst.getSpecName())) {
                    prodInst.setSpecName(ProductCache.get(prodInst.getSpecId()).getProdName());
                }
                chargeOrderItemAndFeeDTO.setOfferName(prodInst.getSpecName());
            }
            else {
                // 过程单不存在则取在用实例表
                OrderItem item = procInstMap.get(chargeOrderItemAndFeeDTO.getObjId());
                if (Objects.isNull(item)) {
                    // 过程单不存在则取在用实例表
                    item = useInstMap.get(chargeOrderItemAndFeeDTO.getObjId());
                }
                if (!Objects.isNull(item)) {
                    chargeOrderItemAndFeeDTO.setAccNum(item.getAccNum());
                    chargeOrderItemAndFeeDTO.setOfferName(item.getSpecName());
                }
                //避免排序报空指针
                chargeOrderItemAndFeeDTO.setRoleId("");
            }
            long time2 = System.currentTimeMillis();
            LOGGER.debug("取产品规格==============" + (time2 - time1));
        }
        // 功能产品
        else if (Objects.equals(KeyConsts.EVT_0003_1301, chargeOrderItemAndFeeDTO.getCartItemCd())) {
            long time1 = System.currentTimeMillis();
            Product product = ProductCache.get(chargeOrderItemAndFeeDTO.getApplyObjSpec());
            chargeOrderItemAndFeeDTO.setSpecName(Optional.ofNullable(product).map((p) -> p.getProdName()).orElse(""));
            KiteProdInstFunc prodInstFunc = querySceneInstService.getProdInstFunc(chargeOrderItemAndFeeDTO.getCustId(),
                chargeOrderItemAndFeeDTO.getObjId());
            if (!Objects.isNull(prodInstFunc)) {
                KiteProdInst prodInst = querySceneInstService.getProdInstByFuncProdInstId(chargeOrderItemAndFeeDTO.getCustId(), prodInstFunc.getInstId());
                if (!Objects.isNull(prodInst)) {
                    chargeOrderItemAndFeeDTO.setAccNum(prodInst.getAccNum());
                }
                else {
                    // 过程单不存在则取在用实例表
                    OrderItem item = useInstMap.get(chargeOrderItemAndFeeDTO.getObjId());
                    if (item != null) {
                        chargeOrderItemAndFeeDTO.setAccNum(item.getAccNum());
                    }
                }
            }
            long time2 = System.currentTimeMillis();
            LOGGER.debug("取功能产品规格==============" + (time2 - time1));
        }
        //取费用项服务提供名称
        String feeServiceName = Optional.ofNullable(ServiceOfferCache.get(chargeOrderItemAndFeeDTO.getFeeServiceOfferId()))
                .map(servOffer -> {
                    return I18nUtil.getMessage("BSS_KITE_ACCEPT_90018") + servOffer.getServiceOfferName()
                        + I18nUtil.getMessage("BSS_KITE_ACCEPT_90019");
                }).orElse("");
        chargeOrderItemAndFeeDTO.setFeeServiceOfferName(feeServiceName);
        return chargeOrderItemAndFeeDTO;
    }

    @Override
    public DataResult<List<ShoppingCartItemFeeDTO>> listPosShoppingCartItemFees(String sceneInstId, String custId) {
        List<PosShoppingCartItemFee> hisFees = shoppingCartItemFeeMapper.listPosShoppingCartItemFees(sceneInstId, custId);
        return ErrorConsts.SUCCESS.getResult(KiteBeanUtils.copyPropsForList(hisFees, ShoppingCartItemFeeDTO.class));
    }

    @Override
    public DataResult<ShoppingCartItemDTO> getShoppingCartItem(String cartItemId, String custId) {
        Assert.hasText(cartItemId, "cartItemId must not be empty");
        Example example = new Example(KiteShoppingCartItem.class);
        example.createCriteria().andEqualTo("cartItemId", cartItemId).andEqualTo("custId", custId);
        KiteShoppingCartItem shoppingCartItem = shoppingCartItemMapper.selectOneByExample(example);
        return ErrorConsts.SUCCESS
            .getResult(KiteBeanUtils.transform(shoppingCartItem, ShoppingCartItemDTO.class));
    }

    @Override
    public DataResult<ShoppingCartItemDTO> getShoppingCartItem(String custOrderId, String objId, String cartItemId, String custId) {
        if (KiteStringUtils.isEmpty(cartItemId) && KiteStringUtils.isEmpty(objId)) {
            return ErrorConsts.SUCCESS.getResult(new ShoppingCartItemDTO());
        }
        List<KiteShoppingCartItem> shoppingCartItems = null;
        Example example = new Example(KiteShoppingCartItem.class);
        if (!KiteStringUtils.isEmpty(cartItemId)) {
            example.createCriteria().andEqualTo("cartItemId", cartItemId).andEqualTo("custId", custId);
            shoppingCartItems = shoppingCartItemMapper.selectByExample(example);
        }
        else if (!KiteStringUtils.isEmpty(objId)) {
            example.createCriteria().andEqualTo("objId", objId).andEqualTo("custId", custId);
            shoppingCartItems = shoppingCartItemMapper.selectByExample(example);
        }
        if (KiteListUtils.isEmpty(shoppingCartItems) || shoppingCartItems.size() > 1) {
            ErrorConsts.SHOPPING_CART_DATA_ERROR.throwOut(custOrderId);
        }
        return ErrorConsts.SUCCESS
            .getResult(KiteBeanUtils.transform(shoppingCartItems.get(0), ShoppingCartItemDTO.class));
    }

    @Override
    public DataResult<List<ShoppingCartItemFeeDTO>> getShoppingCartItemFees(String cartItemId, String custId) {
        Example example = new Example(KiteShoppingCartItemFee.class);
        example.createCriteria().andEqualTo("cartItemId", cartItemId).andEqualTo("custId", custId);
        List<KiteShoppingCartItemFee> shoppingCartItemFees = shoppingCartItemFeeMapper.selectByExample(example);
        return ErrorConsts.SUCCESS
            .getResult(KiteBeanUtils.copyPropsForList(shoppingCartItemFees, ShoppingCartItemFeeDTO.class));
    }

    @Override
    public ShoppingCartItemDTO getShoppingCartItemDTO(String sceneInstId, String objId, String staffId, String custId) {
        ShoppingCartItemDTO itemDTO = ShoppingCartGroupCache.getShoppingCartItemDto(staffId, custId, sceneInstId, objId);
        if (!Objects.isNull(itemDTO)) {
            return itemDTO;
        }

        Example example = new Example(KiteShoppingCartItem.class);
        example.createCriteria().andEqualTo("statusCd", KeyConsts.SHOPPING_CART_ITEM_STATUS_VALIDATE)
                .andEqualTo("objId", objId).andEqualTo("custId", custId).andEqualTo("groupId", sceneInstId);
        KiteShoppingCartItem shoppingCartItem = shoppingCartItemMapper.selectOneByExample(example);
        if (Objects.isNull(shoppingCartItem)) {
            return itemDTO;
        }
        itemDTO = KiteBeanUtils.transform(shoppingCartItem, ShoppingCartItemDTO.class);
        itemDTO.setProdInstId(shoppingCartItem.getObjId());
        itemDTO.setApplyObjSpec(shoppingCartItem.getApplyObjSpec());
        return itemDTO;
    }

    @Override
    public ShoppingCartItemDTO getShoppingCartItemDTOByNotStatus(String sceneInstId, String objId, String staffId, String custId) {
        Example example = new Example(KiteShoppingCartItem.class);
        example.createCriteria().andEqualTo("objId", objId).andEqualTo("custId", custId).andEqualTo("groupId", sceneInstId);
        KiteShoppingCartItem shoppingCartItem = shoppingCartItemMapper.selectOneByExample(example);
        ShoppingCartItemDTO itemDTO = KiteBeanUtils.transform(shoppingCartItem, ShoppingCartItemDTO.class);
        if (Objects.nonNull(shoppingCartItem)) {
            itemDTO.setProdInstId(shoppingCartItem.getObjId());
            itemDTO.setApplyObjSpec(shoppingCartItem.getApplyObjSpec());
        }
        return itemDTO;
    }

    @Override
    public List<ShoppingCartGroupInstDTO> listShoppingCartGroups(List<String> sceneInstIds, String staffId, String lanId, String custId) {
        Assert.hasText(custId, "sceneInstId must not be empty");
        List<ShoppingCartGroupInstDTO> rtnGroups = new ArrayList<ShoppingCartGroupInstDTO>();
        if (KiteListUtils.isEmpty(sceneInstIds)) {
            return rtnGroups;
        }
        // 获取购物车分组
        List<ShoppingCartGroupInstDTO> groups = this.listShoppingCartGroups(staffId, lanId, custId);
        if (!KiteListUtils.isEmpty(groups)) {
            for (ShoppingCartGroupInstDTO group : groups) {
                if (sceneInstIds.contains(group.getGroupId())) {
                    rtnGroups.add(group);
                }
            }
        }
        return rtnGroups;
    }

    @Override
    public List<ShoppingCartGroupInstDTO> listShoppingCartGroupsByItemServiceOfferId(String instId, String serviceOfferId, String staffId, String custId, String lanId) {
        List<ShoppingCartGroupInstDTO> rtmGroupInsts = new ArrayList<ShoppingCartGroupInstDTO>();
        List<ShoppingCartGroupInstDTO> groupInsts = this.listShoppingCartGroups(staffId, lanId, custId);
        groupInsts.forEach((group) -> {
            List<ShoppingCartItemDTO> items = group.getShoppingCartItems();
            for (ShoppingCartItemDTO item : items) {
                if (KiteStringUtils.equals(instId, item.getObjId()) && KiteStringUtils.equals(serviceOfferId, item.getServiceOfferId())
                        && KiteStringUtils.equals(custId, item.getCustId())) {
                    rtmGroupInsts.add(group);
                    break;
                }
            }
        });
        return rtmGroupInsts;
    }

    @Override
    public List<ShoppingCartGroupInstDTO> listCorrectGroupInstsByCustOrderIds(List<String> custOrderIds, String custId, String operType) {
        List<KiteShoppingCartGroupInst> groupInsts = shoppingCartGroupInstMapper.listCorrectGroupInstsByCustOrderIds(custOrderIds, custId, operType);
        return KiteBeanUtils.copyPropsForList(groupInsts, ShoppingCartGroupInstDTO.class);
    }

    @Override
    public List<ShoppingCartGroupInstDTO> listAllCorrectGroupInsts(String oldGroupId, String custId) {
        List<KiteShoppingCartGroupInst> groupInsts = shoppingCartGroupInstMapper.listAllCorrectGroupInsts(oldGroupId, custId);
        return KiteBeanUtils.copyPropsForList(groupInsts, ShoppingCartGroupInstDTO.class);
    }

    @Override
    public DataResult<List<ShoppingCartGroupInstDTO>> getGroupInstDTOByCustOrderId(String custOrderId, String custId) {
        Example example = new Example(KiteShoppingCartGroupInst.class);
        example.createCriteria().andEqualTo("custOrderId", custOrderId).andEqualTo("custId", custId);
        List<KiteShoppingCartGroupInst> groupInsts = shoppingCartGroupInstMapper.selectByExample(example);
        if (KiteListUtils.isEmpty(groupInsts)) {
            //从历史表查
            groupInsts = shoppingCartGroupInstMapper.selectShoppingCartGroupInstsFromHis(null, custId, null, custOrderId, null);
            if (KiteListUtils.isEmpty(groupInsts)) {
                return ErrorConsts.SUCCESS.getResult(null);
            }
        }
        return ErrorConsts.SUCCESS.getResult(KiteBeanUtils.copyPropsForList(groupInsts, ShoppingCartGroupInstDTO.class));
    }

    @Override
    public DataResult<List<ShoppingCartGroupInstDTO>> getGroupInstDTOWidthoutHisByCustOrderId(String custOrderId, String custId) {
        Example example = new Example(KiteShoppingCartGroupInst.class);
        example.createCriteria().andEqualTo("custOrderId", custOrderId).andEqualTo("custId", custId);
        List<KiteShoppingCartGroupInst> groupInsts = shoppingCartGroupInstMapper.selectByExample(example);
        if (KiteListUtils.isEmpty(groupInsts)) {
            return ErrorConsts.SUCCESS.getResult(null);
        }
        return ErrorConsts.SUCCESS.getResult(KiteBeanUtils.copyPropsForList(groupInsts, ShoppingCartGroupInstDTO.class));
    }

    @Override
    public DataResult<ShoppingCartGroupInstDTO> getGroupInstDTOByCustOrderIdAndStatus(String custOrderId, String custId, List<String> statusCds) {
        Example example = new Example(KiteShoppingCartGroupInst.class);
        example.createCriteria().andEqualTo("custOrderId", custOrderId).andEqualTo("custId", custId).andIn("statusCd", statusCds);
        KiteShoppingCartGroupInst groupInst = shoppingCartGroupInstMapper.selectOneByExample(example);
        if (Objects.isNull(groupInst)) {
            //从历史表查
            List<KiteShoppingCartGroupInst> groupInsts = shoppingCartGroupInstMapper.selectShoppingCartGroupInstsFromHis(null, custId, statusCds, custOrderId, null);
            if (KiteListUtils.isEmpty(groupInsts)) {
                return ErrorConsts.SUCCESS.getResult(null);
            }
            groupInst = groupInsts.get(0);
        }
        return ErrorConsts.SUCCESS.getResult(KiteBeanUtils.transform(groupInst, ShoppingCartGroupInstDTO.class));
    }

    @Override
    public DataResult<List<ShoppingCartGroupInstDTO>> getGroupInstDTOByOrderItemId(String orderItemId, String custId) {
        Example orderItemQry = new Example(OrderItem.class);
        orderItemQry.createCriteria().andEqualTo("orderItemId", orderItemId).andEqualTo("belongCustId", custId);
        OrderItem orderItem = this.orderItemMapper.selectOneByExample(orderItemQry);
        if (!KiteObjectUtils.isEmpty(orderItem)) {
            String custOrderId = orderItem.getCustOrderId();
            return this.getGroupInstDTOByCustOrderId(custOrderId, custId);
        }
        return ErrorConsts.SUCCESS.getResult(null);
    }

    @Override
    public DataResult<ShoppingCartGroupInstDTO> getGroupInstDTOByGroupId(String groupId, String custId) {
        Example example = new Example(KiteShoppingCartGroupInst.class);
        example.createCriteria().andEqualTo("groupId", groupId).andEqualTo("custId", custId);
        KiteShoppingCartGroupInst groupInst = shoppingCartGroupInstMapper.selectOneByExample(example);
        if (Objects.isNull(groupInst)) {
            return ErrorConsts.SUCCESS.getResult(null);
        }
        return ErrorConsts.SUCCESS.getResult(KiteBeanUtils.transform(groupInst, ShoppingCartGroupInstDTO.class));
    }

    @Override
    public DataResult<ShoppingCartGroupInstDTO> getShoppingGroupInstHis(String groupId, String custId) {
            //从历史表取
        KiteShoppingCartGroupInst groupInst = shoppingCartGroupInstMapper.getShoppingGroupInstHis(groupId, custId);
            if (Objects.isNull(groupInst)) {
                return ErrorConsts.SUCCESS.getResult(null);
            }
        return ErrorConsts.SUCCESS.getResult(KiteBeanUtils.transform(groupInst, ShoppingCartGroupInstDTO.class));
    }

    @Override
    public DataResult<ShoppingCartGroupInstDTO> getShoppingGroupInstHisByCustOrderId(String groupId, String custId) {
            //从历史表取
        KiteShoppingCartGroupInst groupInst = shoppingCartGroupInstMapper.getShoppingGroupInstHis(groupId, custId);
            if (Objects.isNull(groupInst)) {
                return ErrorConsts.SUCCESS.getResult(null);
            }
        return ErrorConsts.SUCCESS.getResult(KiteBeanUtils.transform(groupInst, ShoppingCartGroupInstDTO.class));
    }

    @Override
    public DataResult<ShoppingCartGroupInstDTO> getRevokeShoppingGroupInstDTO(String custOrderId, String custId) {
        KiteShoppingCartGroupInst groupInst = shoppingCartGroupInstMapper.getRevokeShoppingGroupInst(custOrderId, custId);
        if (Objects.isNull(groupInst)) {
            groupInst = shoppingCartGroupInstMapper.getRevokeShoppingGroupInstFromHis(custOrderId, custId);
        }
        if (Objects.isNull(groupInst)) {
            return ErrorConsts.SUCCESS.getResult(null);
        }
        return ErrorConsts.SUCCESS.getResult(KiteBeanUtils.transform(groupInst, ShoppingCartGroupInstDTO.class));
    }

    @Override
    public DataResult<ShoppingCartGroupInstDTO> getWithdrawShoppingGroupInstDTOWithoutHis(String custOrderId, String custId) {
        KiteShoppingCartGroupInst groupInst = shoppingCartGroupInstMapper.getRevokeShoppingGroupInst(custOrderId, custId);
        if (Objects.isNull(groupInst)) {
            return ErrorConsts.SUCCESS.getResult(null);
        }
        return ErrorConsts.SUCCESS.getResult(KiteBeanUtils.transform(groupInst, ShoppingCartGroupInstDTO.class));
    }

    @Override
    public DataResult<List<ShoppingCartGroupInstDTO>> listShoppingCartGroupInstsBySerial(String shoppingCartSerial,
            String custId) {
        List<KiteShoppingCartGroupInst> groupInsts = shoppingCartGroupInstMapper.listShoppingCartGroupInstsBySerialId(custId, shoppingCartSerial);
        return ErrorConsts.SUCCESS.getResult(KiteBeanUtils.copyPropsForList(groupInsts, ShoppingCartGroupInstDTO.class));
    }
    @Override
    public ShoppingCartGroupInstAttrDTO getShoppingCartGroupInstAttr(String groupId, String custId, String fieldName) {
        Example example = new Example(KiteShoppingCartGroupInstAttr.class);
        example.createCriteria().andEqualTo("groupId", groupId).andEqualTo("custId", custId).andEqualTo("fieldName", fieldName);
        List<KiteShoppingCartGroupInstAttr> attrList = shoppingCartGroupInstAttrMapper.selectByExample(example);
        KiteShoppingCartGroupInstAttr attr = null;
        if (KiteListUtils.isNotEmpty(attrList)) {
            attr = attrList.get(0);
        }
        return KiteBeanUtils.transform(attr, ShoppingCartGroupInstAttrDTO.class);
    }
    @Override
    public SimpleLoginInfo getSimpleLoginInfo(String userId, String lanId) {
        SimpleLoginInfo simpleLoginInfo = ContextUtil.getSimpleLoginInfo();
        if (Objects.isNull(simpleLoginInfo) || !KiteStringUtils
                .equals(String.valueOf(simpleLoginInfo.getUserId()), userId) || !KiteStringUtils
                .equals(simpleLoginInfo.getLanId(), lanId)) {
            if (KiteStringUtils.isEmpty(userId) || KiteStringUtils.isEmpty(lanId)) {
                ErrorConsts.PARAMETER_USERID_LANID_NULL_ERROR.throwOut();
            }

            OrderLoginReq orderLoginReq = new OrderLoginReq();
            orderLoginReq.setQryScene(OrderLoginReq.QryScene.USER_ID);
            orderLoginReq.setUserId(Long.valueOf(userId));
            orderLoginReq.setLanId(lanId);
            OrderLoginResp orderLoginResp = orderLoginService.qryLoginInfo(orderLoginReq);

            simpleLoginInfo = new SimpleLoginInfo();
            simpleLoginInfo.setUserId(orderLoginResp.getUserInfo().getUserId());
            simpleLoginInfo.setOrgId(orderLoginResp.getOrgInfo().getOrgId());
            simpleLoginInfo.setPostId(orderLoginResp.getUserInfo().getPostId());
            simpleLoginInfo.setLanId(orderLoginResp.getUserInfo().getPostLanId());
        }
        return simpleLoginInfo;
    }

    @Override
    public List<ShoppingCartGroupInstDTO> getChargingGroupInstDtos(String staffId, String custId) {
        return ShoppingCartGroupCache.getGroupInstDtos(staffId, custId, KeyConsts.SHOPPING_CART_GROUP_STATUS_CHARGING);
    }

    @Override
    public ShoppingCartGroupInstDTO getGroupInstDto(String staffId, String custId, String groupId) {
        return ShoppingCartGroupCache.getGroupInstDto(staffId, custId, groupId);
    }

    @Override
    public List<ShoppingCartGroupInstDTO> listModifyShoppingCartGroupInstDtos(String groupId, String custId, String operType) {
        Example example = new Example(KiteShoppingCartGroupInst.class);
        example.createCriteria().andEqualTo("oldGroupId", groupId).andEqualTo("custId", custId).andEqualTo("operType", operType);
        List<KiteShoppingCartGroupInst> groupInsts = shoppingCartGroupInstMapper.selectByExample(example);
        return KiteBeanUtils.copyPropsForList(groupInsts, ShoppingCartGroupInstDTO.class);
    }

    @Override
    public Map<String, String> listOrderInstRelsByCustOrderId(String custOrderId, String custId) {
        Map<String, String> orderInstIdMap = new HashMap<>();
        Example example = new Example(KiteOrderInstRel.class);
        example.createCriteria().andEqualTo("custOrderId", custOrderId).andEqualTo("ownerCustId", custId);
        KiteOrderInstRelMapper mapper = SpringUtil.getBean(KiteOrderInstRelMapper.class);
        List<KiteOrderInstRel> orderInstRels = mapper.selectByExample(example);
        if (CollectionUtils.isEmpty(orderInstRels)) {
            return Collections.emptyMap();
        }

        for (KiteOrderInstRel orderInstRel : orderInstRels) {
            String kiteInstType = orderInstRel.getInstType();
            String kiteInstId = orderInstRel.getaInstId();
            String orderInstId = orderInstRel.getzInstId();
            if (KiteStringUtils.isAnyBlank(kiteInstType, kiteInstId, orderInstId)) {
                continue;
            }

            String key = ManagerUtils.join(kiteInstType, kiteInstId);
            orderInstIdMap.put(key, orderInstId);
        }
        return orderInstIdMap;
    }

    @Override
    public String getOldGroupInstTotalAmount(String groupId, String custId) {
        Example example = new Example(KiteShoppingCartItem.class);
        example.createCriteria().andEqualTo("groupId", groupId).andEqualTo("custId", custId);
        List<KiteShoppingCartItem> items = this.shoppingCartItemMapper.selectByExample(example);
        List<String> cartItemIds = new ArrayList<String>();
        for (KiteShoppingCartItem item : items) {
            custId = item.getCustId();
            cartItemIds.add(item.getCartItemId());
        }
        return shoppingCartItemFeeMapper.sumHisShoppingCartItemFees(cartItemIds, custId);

    }

    @Override
    public DataResult<List<ChargeCartItemAndFeeDTO>> listTransferFailShpCartItemsAndFees(String custOrderId, String custId) {
        return this.listShoppingCartItemsAndFees(custOrderId, custId, "");
    }

    @SuppressWarnings("deprecation")
    @Override
    public String getCheckEmergencyOrderFee(List<String> sceneInstIds, String custId, String allAmount) {
        String msg = "";
        String oldAmount = "";
        String flag = DcPublicCache.getCodea("2019112708", "check_emergency_order_fee_flag");
        if ("T".equals(flag) || ListUtil.isEmpty(sceneInstIds) || StringUtil.isEmpty(allAmount)) {
            return msg;
        }

        // 加上收银台的费用
        ShoppingCartItemFeeMapper cartItemFeeMapper = SpringUtil.getBean(ShoppingCartItemFeeMapper.class);
        String extAmount = cartItemFeeMapper.getEmergencyAmountExt(sceneInstIds, custId);
        if (!StringUtil.isEmpty(extAmount)) {
            double allAmountD = Double.valueOf(allAmount);
            double extAmountD = Double.valueOf(extAmount);
            allAmountD = allAmountD + extAmountD;
            allAmount = allAmountD + "";
        }

        for (String sceneInstId : sceneInstIds) {
            KiteShoppingCartGroupInstAttr attr = shoppingCartGroupInstAttrMapper.getGroupInstAttrInfoByFieldName(sceneInstId,
                    custId, "record_id");
            if (attr == null || StringUtil.isEmpty(attr.getAttrValue())) {
                continue;
            }
            oldAmount = shoppingCartGroupInstAttrMapper.getTotalFeeByRecordId(attr.getAttrValue());
            break;
        }

        if (StringUtil.isEmpty(oldAmount)) {
            return msg;
        }
        //极简算费总金额
        BigDecimal allAmountB = new BigDecimal(allAmount).setScale(2, RoundingMode.HALF_UP);
        //应急留单费用
        BigDecimal oldAmountB = new BigDecimal(oldAmount).setScale(2, RoundingMode.HALF_UP);
        int amountSubInt = allAmountB.compareTo(oldAmountB);
        BigDecimal amountSubb = null;
        if (amountSubInt == 0) {
            return msg;
        }
        else if (amountSubInt < 0) {
            // 留单的金额 > 算出来金额
            amountSubb = oldAmountB.subtract(allAmountB).setScale(2, RoundingMode.HALF_UP);
            ErrorConsts.EMERGENCY_ORDER_CHECK_ERROR_1.throwOut(oldAmountB.toString(), allAmountB.toString(),
                    amountSubb.toString());
        }
        else if (amountSubInt > 0) {
            // 算出来金额 > 当留单的金额
            amountSubb = allAmountB.subtract(oldAmountB).setScale(2, RoundingMode.HALF_UP);
            // 判断当前工号是否为代理商
            String orgSubType = ContextUtil.getLoginInfo().getOrgInfo().getOrgSubtype() + "";
            if (StrTools.isEqual(orgSubType, IKeyValues.ORG_SUBTYPE_1800)) {
                // 工号是代理商
                msg = I18nUtil.getMessage("BSS_KITE_SHOPPING_CART_42047", oldAmountB.toString(), allAmountB.toString(),
                        amountSubb.toString());
            }
            else {
                msg = I18nUtil.getMessage("BSS_KITE_SHOPPING_CART_42048", oldAmountB.toString(), allAmountB.toString(),
                        amountSubb.toString());
            }
        }
        return msg;
    }

    @Override
    public List<ShoppingCartGroupInstDTO> getGroupInstOrHisByCustOrderId(String custOrderId, String custId) {
        List<KiteShoppingCartGroupInst> groupInsts = shoppingCartGroupInstMapper.getGroupInstOrHisByCustOrderId(custId,
            custOrderId);
        return KiteBeanUtils.copyPropsForList(groupInsts, ShoppingCartGroupInstDTO.class);
    }

    @Override
    public String getAccNum(String cartItemCd, String objId, String custId) {
        if (KeyConsts.SHOPPING_CART_ITEM_CD_CP.equals(cartItemCd)
            || KeyConsts.SHOPPING_CART_ITEM_CD_GNCP.equals(cartItemCd)
            || KeyConsts.SHOPPING_CART_ITEM_CD_YXZY.equals(cartItemCd)) {
            List<String> accNumList = orderItemMapper.getAccNumfromOrdProdInst(objId, custId);
            if (!KiteListUtils.isEmpty(accNumList)) {
                return accNumList.get(0);
            }
            else {
                List<String> accNumHisList = orderItemMapper.getAccNumfromOrdProdInstHis(objId, custId);
                if (!KiteListUtils.isEmpty(accNumHisList)) {
                    return accNumHisList.get(0);
                }
            }
        }
        return "";
    }

    @Override
    public void getSceneInst(String groudId, String custId) {
        RuleUtil.getQuerySceneInstService().getSceneInst(groudId, custId);
    }

    public String getOrderCancelBtnFlag() {
        String userCode = ContextUtil.getSimpleLoginInfo().getUserCode();
        String stype = "19121308";
        String pkeyStaff = "sys_user_codes";
        String pkeyPriv = "priv_code";
        // 1.允许特定工号取消订单
        String userCodes = DcPublicCache.getCodea(stype, pkeyStaff);
        if (StringUtil.isNotEmpty(userCodes) && userCodes.toLowerCase().contains("," + userCode.toLowerCase() + ",")) {
            return "1";
        }
        // 2.允许拥有特定权限的工号可以取消订单
        String privCode = DcPublicCache.getCodea(stype, pkeyPriv);
        if (StringUtil.isNotEmpty(privCode)
                && ContextUtil.getLoginInfo().checkRightByPrivCode(privCode.toUpperCase())) {
            return "1";
        }
        return "0";
    }

    @Override
    public void checkOrderCancel(ShoppingCartGroupInstDTO groupInstDTO, String custId) {
        String serviceOfferId = groupInstDTO.getServiceOfferId();
        String userCode = ContextUtil.getSimpleLoginInfo().getUserCode();
        String stype = "19121308";
        String pkeyStaff = "sys_user_codes";
        String pkeyPriv = "priv_code";
        String pkeyServiceOffers = "service_offer_ids";
        // 0.限制特定业务才能做取消
        String serviceOfferIds = DcPublicCache.getCodea(stype, pkeyServiceOffers);
        if (StringUtil.isEmpty(serviceOfferIds) || !serviceOfferIds.contains("," + serviceOfferId + ",")) {
            ServiceOffer serviceOffer = ServiceOfferCache.get(serviceOfferId);
            String serviceOfferName = serviceOfferId;
            if (serviceOffer != null) {
                serviceOfferName = serviceOffer.getServiceOfferName();
            }
            ErrorConsts.CHECK_SERVICE_OFFER_CANCEL.throwOut(serviceOfferName);
        }
        // 1.允许特定工号取消订单
        String userCodes = DcPublicCache.getCodea(stype, pkeyStaff);
        if (StringUtil.isNotEmpty(userCodes) && userCodes.toLowerCase().contains("," + userCode.toLowerCase() + ",")) {
            return;
        }
        // 2.允许拥有特定权限的工号可以取消订单
        String privCode = DcPublicCache.getCodea(stype, pkeyPriv);
        if (StringUtil.isNotEmpty(privCode) && ContextUtil.getLoginInfo().checkRightByPrivCode(privCode.toUpperCase())) {
            return;
        }
        ErrorConsts.CHECK_ORDER_CANCEL.throwOut(userCode);
    }

    @Override
    public RefundOrderDTO getRefundOrder(String custOrderId, String custId, ShoppingCartGroupInstDTO groupInstDTO) {
        KiteSceneInst sceneInst = RuleUtil.getQuerySceneInstService().getSceneInst(groupInstDTO.getGroupId(), custId);
        String serviceOfferId = sceneInst.getServiceOfferId();
        String sceneInstName = sceneInst.getSceneInstName();
        ServiceOffer serviceOffer = ServiceOfferCache.get(serviceOfferId);
        String serviceOfferName = serviceOfferId;
        if (serviceOffer != null) {
            serviceOfferName = serviceOffer.getServiceOfferName();
        }
        ShoppingCartItemFeeMapper cartItemFeeMapper = SpringUtil.getBean(ShoppingCartItemFeeMapper.class);
        String notRefundAmount = cartItemFeeMapper.getNotRefundAmountByCustOrderId(custOrderId, custId,
                CoreDataBilling.OTC_0001_120000);
        String refundAmount = cartItemFeeMapper.getRefundAmountByCustOrderId(custOrderId, custId,
                CoreDataBilling.OTC_0001_120000);
        if (FeeCalUtil.isZero(notRefundAmount)) {
            notRefundAmount = "0.00";
        }
        if (FeeCalUtil.isZero(refundAmount)) {
            refundAmount = "0.00";
        }
        RefundOrderDTO refundOrderDTO = new RefundOrderDTO();
        refundOrderDTO.setCustOrderId(custOrderId);
        refundOrderDTO.setCustId(custId);
        refundOrderDTO.setOrderDesc("[" + serviceOfferName + "]-" + sceneInstName);
        refundOrderDTO.setNotRefundAmount(notRefundAmount);
        refundOrderDTO.setRefundAmount(refundAmount);
        return refundOrderDTO;
    }

    public boolean transferSuceessCheck(List<String> groupIds) {
        return transferSuceessCheck(groupIds, null);
    }

    public boolean transferSuceessCheck(List<String> groupIds, String custId) {
        List<String> custOrderIds = shoppingCartGroupInstMapper.getTransferFlag(groupIds, custId);
        Example example = new Example(OrderItem.class);
        Criteria criteria = example.createCriteria().andIn("custOrderId", custOrderIds);
        if (KiteStringUtils.isNotEmpty(custId)) {
            criteria.andEqualTo("belongCustId", custId);
        }
        List<OrderItem> orderItems = orderItemMapper.selectByExample(example);
        return CollectionUtils.isNotEmpty(orderItems);
    }
}
